﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BusTrackerSystem.Model;
using System.Xml;
using System.IO;

namespace BusTrackerSystem.Utility
{
    /// <summary>
    /// A class to decipher the XHTML returned from the http://mybustracker.co.uk/getBusStopDepartures.php page.
    /// This code is based on work by Niall Scott available here: http://code.google.com/p/androidedinburghbustracker/source/browse/
    /// </summary>
    public static class MyBusTrackerParser
    {
        public static List<BusTime> ParseBusTimeInformation(System.Net.WebResponse response)
        {
            //if (response == null) return null;

            StreamReader reader = new StreamReader(response.GetResponseStream());
            XmlReader xmlReader = XmlReader.Create(reader);

            var busTimes = new List<BusTime>();
            BusTime lastBusTime = null;
            while (xmlReader.Read())
            {
                //Pre is used to denote a new bus time slot
                if (xmlReader.Name == "pre")
                {
                    string info = xmlReader.ReadString();
                    if (info != "")
                    {
                        bool isAccessible = false;
                        //An end element denotes that there are no elements inside it (e.g. a span to indicate accessibility)
                        if (xmlReader.NodeType != XmlNodeType.EndElement)
                        {
                            xmlReader.Read();
                            xmlReader.Read();
                            //Span is used to denote accessibility
                            if (xmlReader.Name == "span")
                            {
                                isAccessible = true;

                                //Append the ETA - appears after this span
                                xmlReader.Read();
                                info += xmlReader.ReadString();
                            }
                        }

                        lastBusTime = MyBusTrackerParser.ParseBusTimeInformation(info);

                        if (lastBusTime != null)
                        {
                            if (isAccessible)
                                lastBusTime.IsAccessible = true;
                            busTimes.Add(lastBusTime);
                        }
                    }
                }
            }
            return busTimes;
        }

        private static BusTime ParseBusTimeInformation(string busTimeLine) 
        {
            //TODO: Make this a (proper) regular expression
            String[] busTimeInformationSplit = busTimeLine.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
            if (busTimeInformationSplit.Length < 3)
                return null;
                //throw new InvalidOperationException("The bus tracker line does not contain at least 3 elements: Route number, destination and time remanining.");

            //Will take the form [routeNumber]   [destination] [accessibility]   [timeRemaining]
            var routeNumber = busTimeInformationSplit[0].Trim();

            string timeRemaining = busTimeInformationSplit[busTimeInformationSplit.Length - 1].Trim();
            bool isEstimatedTime = false;
            ParseTime(ref timeRemaining, ref isEstimatedTime);

            string destination = "";
            bool isAccessible = false;
            ParseDestinationAndAccessibility(busTimeInformationSplit, ref destination, ref isAccessible);
            return new BusTime(routeNumber, destination, isAccessible, timeRemaining, isEstimatedTime);
        }

        private static void ParseDestinationAndAccessibility(string[] busTimeInformationSplit, ref string destination, ref bool isAccessible)
        {
            if (busTimeInformationSplit.Length == 3)
            {
                destination = busTimeInformationSplit[1].Trim();
            }
            else
            {
                destination = busTimeInformationSplit[1];
                for (int i = 2; i < busTimeInformationSplit.Length - 1; i++)
                {
                    destination += " " + busTimeInformationSplit[i];
                }
                //TODO: Get the fucking accessibility from that span shit
            }
        }

        private static void ParseTime(ref string timeRemaining, ref bool isEstimatedTime)
        {
            if (timeRemaining.Equals("DUE") || timeRemaining.Equals("*DUE")) return;
            //Handle estimated times
            if (timeRemaining.Contains('*'))
            {
                isEstimatedTime = true;
                //timeRemaining = timeRemaining.Replace("*", "");
            }
            if (!timeRemaining.Contains(':'))
            {
                timeRemaining += "mins";
            }
        }
    }
}
